/**
 * 玩法热更工具
 * @type {object}
 */
var SubUpdateUtil = {
    _assetsManager: null,
    _assetsManagerListener: null,
    _callback: null,
    _newVersion: null,
    _messages: {},
    _filterCode: [
        // MsgCode.Login,
        // MsgCode.SubUpdate,
        // MsgCode.JoinRoom,
        // MsgCode.CreateRoom
    ],
    /**
     * 旧的玩法模块代码
     * @private
     */
    _oldSubSrc: [],
    /**
     * 打开creatRoom界面
     * @param sub
     * @param isDaikai
     * @param club_id
     * @param isSetWanfa
     * @param setwanfapos
     * @param subAddit
     */
    showCreateRoom: function (sub, isDaikai, club_id, isSetWanfa, setwanfapos, subAddit) {
        // this._showCreateRoomWindow( sub, isDaikai, club_id, isSetWanfa, setwanfapos, subAddit);
        this._loadMain(sub, function () {
            showWindow('SubCreateRoomWindow', sub, isDaikai, club_id, isSetWanfa, setwanfapos, subAddit);
        });
        return;
        showDownLoading('解析资源中...', '');
        this._newVersion = null;
        this._callback = null;
        var self = this;
        if (this._needEnforceUpdate(sub)) {
            this._revertSubVersion(sub);
            this._requestSubVersion(sub, function (version) {
                self.checkUpdate(null, sub, version, function () {
                    self._showCreateRoomWindow(sub, isDaikai, club_id, isSetWanfa, setwanfapos, subAddit);
                });
            });
        } else {
            this._showCreateRoomWindow(sub, isDaikai, club_id, isSetWanfa, setwanfapos, subAddit);
        }
    },
    _showCreateRoomWindow: function (sub, isDaikai, club_id, isSetWanfa, setwanfapos, subAddit) {
        var self = this;
        self._loadSub(sub, function () {
            showWindow('SubCreateRoomWindow', sub, isDaikai, club_id, isSetWanfa, setwanfapos, subAddit);
        });
    },

    /**
     * 打开checkUpdateSubByMapId界面
     * @param mapId
     * @param callback
     * @param noViewLoading 不显示DownLoading
     */
    checkUpdateSubByMapId: function (mapId, callback, noViewLoading) {
        var key = findKey(app.map_id, mapId);
        var sub = null;
        if (key) {
            sub = app.map_id_2_sub[key];
        }
        if (!sub) {
            return showAlert('更新未知模块！');
        }
        this._loadMain(sub, callback);
        return;

        var key = findKey(app.map_id, mapId);
        var sub = null;
        if (key) {
            sub = app.map_id_2_sub[key];
        }
        if (!sub) {
            return showAlert('更新未知模块！');
        }
        this._newVersion = null;
        this._callback = null;
        this._checkUpdateSubData = {
            sub: sub,
            callback: callback
        };
        var self = this;
        if (!noViewLoading) {
            showDownLoading('正在解析模块资源...', '');
        }

        if (this._needEnforceUpdate(sub)) {
            this._revertSubVersion(sub);
            this._requestSubVersion(sub, function (version) {
                self.checkUpdate(null, sub, version, function () {
                    self.updateSubCallback();
                });
            });
        } else {
            if (DeviceUtil.getDebug()) {
                self.updateSubCallback();
                return;
            }
            network.send(2006, {map_id: mapId});
        }
    },
    /**
     * 检测更新后回调
     */
    updateSubCallback: function () {
        var self = this;
        if (self._checkUpdateSubData) {
            var sub = self._checkUpdateSubData.sub;
            self._loadSub(sub, function () {
                hideDownLoading();
                if (self._checkUpdateSubData.callback) {
                    self._checkUpdateSubData.callback(sub);
                } else {
                    showAlert('没有回调方法！');
                }
            });
        }
    },
    /**
     * 打开游戏场景
     * @param data
     * @param roomDataType 数据类型
     */
    showGameScene: function (data, roomDataType) {
        this._newVersion = null;
        this._callback = null;
        var self = this;
        var sub = null;
        switch (roomDataType) {
            case ROOM_DATA_TYPE.REPLAY:
                if (data['3002']) {
                    gameData.mapId = data['3002']['data']['map_id'];
                } else {
                    var option = JSON.parse(data[0]['data']['Option']);
                    gameData.mapId = option['mapid'];
                }
                break;
            case ROOM_DATA_TYPE.CREATE:
            case ROOM_DATA_TYPE.RECONNECT:
            default:
                if (data.Option) {
                    var option = data.Option == '' ? {} : JSON.parse(decodeURIComponent(data.Option));
                    gameData.mapId = option['mapid'];
                } else {
                    gameData.mapId = data['map_id'];
                }
                if (data['match_id'] && gameData.mapId == 2) {
                    gameData.mapId = app.map_id.KWX_MATCH;

                }
                break;
        }
        var key = findKey(app.map_id, gameData.mapId);
        if (key) {
            sub = app.map_id_2_sub[key];
            if (sub === "majiang_hn") {
                sub = "majiang"
            }
        }
        if (!sub) {
            cc.error('未知游戏场景！');
            return;
        }
        network.stop();
        this._loadMain(sub, function () {
            showRoom(data, roomDataType);
        });
        return;
        if (this._needEnforceUpdate(sub)) {
            this._revertSubVersion(sub);
            this._requestSubVersion(sub, function (version) {
                self.checkUpdate(null, sub, version, function () {
                    self._showGameScene(sub, data, roomDataType);
                });
            });
        } else {
            this._showGameScene(sub, data, roomDataType);
        }
    },
    _showGameScene: function (sub, data, roomDataType) {
        this._loadSub(sub, function () {
            showRoom(data, roomDataType);
        });
    },
    /**
     * 判断是否需要更新
     * @param sub
     * @return {Boolean}
     * @private
     */
    _needEnforceUpdate: function (sub) {
        if (DeviceUtil.getDebug()) {
            return false;
        }
        var manifestDirPath = cc.sys.writablePath + sub + '/';
        var subSrc = 'modules/sub/' + sub + '/Config.jsc';
        if (window.inBanShu) {
            return false;
        }
        return cc.sys.isNative && !jsb.fileUtils.isFileExist(manifestDirPath + subSrc);
    },
    /**
     * 还原模块版本
     * @param sub
     * @private
     */
    _revertSubVersion: function (sub) {
        var verjson = getLocalVersion();
        verjson[sub] = '1.0.0';
        cc.sys.localStorage.setItem('sub-version', JSON.stringify(verjson));
    },
    /**
     *
     * @param sub
     * @param callback
     * @private
     */
    _requestSubVersion: function (sub, callback) {
        if (!callback) {
            this._updateFail(sub, '忘了传回调!');
            return;
        }
        if (this._needEnforceUpdate(sub)) {
            this._revertSubVersion(sub);
        } else {
            callback();
            return;
        }

        http.get(app.updateSubUrl + 'sub-v-' + sub + '.manifest',
            function (data) {
                var version = null;
                try {
                    var dataJson = JSON.parse(data);
                    version = dataJson.version;
                } catch (e) {
                }
                callback(version);
            },
            function () {
                hideDownLoading();
                showAlert('拉取模块版本失败!');
            }
        );
    },
    /**
     * 检查更新
     * @param url
     * @param {string} sub 子模块
     * @param {object} version 版本号
     * @param {function} callback
     */
    checkUpdate: function (url, sub, version, callback) {
        if (!sub) {
            this._updateFail(sub, '拉取模块为空!');
            return;
        }
        if (!callback) {
            this._updateFail(sub, '拉取模块回调为空');
            return;
        }
        this._callback = callback;
        var newVersion = version;
        if (!cc.sys.isNative) {
            this._newVersion = version;
            this._saveLocalVersion(sub);
            this._loadSub(sub, callback);
            return;
        }
        var localVersion = getLocalVersion()[sub];
        if (localVersion === newVersion) {
            this._loadSub(sub, callback);
            return;
        }
        this._clearOldFiles(sub);
        var createResult = this._createManiFest(sub);
        if (!createResult) {
            this._updateFail(sub, '创建manifest失败');
            return;
        }
        this._startUpAssetsManager(sub);
    },
    /**
     * 删除旧文件
     */
    _clearOldFiles: function (sub) {
        var manifestDirPath = cc.sys.writablePath + sub + '/';

        var manifestFileName = 'sub-' + sub + '.manifest';
        var manifestFile = manifestDirPath + manifestFileName;
        var vTempFile = manifestDirPath + 'version.manifest.tmp';
        var vFile = manifestDirPath + 'version.manifest';
        var pTempFile = manifestDirPath + 'project.manifest.tmp';
        var pFile = manifestDirPath + 'project.manifest';
        if (!jsb.fileUtils.isDirectoryExist(manifestDirPath)) {
            jsb.fileUtils.createDirectory(manifestDirPath);
        }
        if (jsb.fileUtils.isFileExist(manifestFile)) {
            jsb.fileUtils.removeFile(manifestFile);
        }
        if (jsb.fileUtils.isFileExist(vTempFile)) {
            jsb.fileUtils.removeFile(vTempFile);
        }
        if (jsb.fileUtils.isFileExist(vFile)) {
            jsb.fileUtils.removeFile(vFile);
        }
        if (jsb.fileUtils.isFileExist(pTempFile)) {
            jsb.fileUtils.removeFile(pTempFile);
        }
        if (jsb.fileUtils.isFileExist(pFile)) {
            jsb.fileUtils.removeFile(pFile);
        }
    },
    // /**
    //  * 获取本地的version存档
    //  */
    // getLocalVersion: function () {
    //     var verItem = cc.sys.localStorage.getItem('sub-version');
    //     if (!verItem) {
    //         verItem = this._createLocalVersion();
    //     }
    //     var verjson = {};
    //     try {
    //         verjson = JSON.parse(verItem);
    //     } catch (e) {
    //     }
    //     return verjson;
    // },
    // /**
    //  * 建立新的本地的version存档
    //  */
    // _createLocalVersion: function () {
    //     var verjson = {};
    //     _.forIn(app.sub_module, function (sub) {
    //         verjson[sub] = '1.0.0';
    //     });
    //     return JSON.stringify(verjson);
    // },
    /**
     * 创建manifest(此manifest是假的)
     * @param sub
     * @returns {bool} 建文件是否成功
     */
    _createManiFest: function (sub) {
        var mainfest = {
            packageUrl: app.updateSubUrl + 'update/',
            remoteVersionUrl: app.updateSubUrl + 'sub-v-' + sub + '.manifest',
            remoteManifestUrl: app.updateSubUrl + 'sub-p-' + sub + '.manifest',
            version: '1.0.0',
            groupVersions: {'0': '1.0.0'},
            engineVersion: 'Cocos2d-JS v3.8.1'
        };
        // manifest目录
        var manifestDirPath = cc.sys.writablePath + sub + '/';
        // manifest文件名
        var manifestFileName = 'sub-' + sub + '.manifest';
        // manifest文件
        var manifestFile = manifestDirPath + manifestFileName;
        return jsb.fileUtils.writeStringToFile(JSON.stringify(mainfest), manifestFile);
    },
    /**
     * 启动AssetsManager
     * @param sub
     */
    _startUpAssetsManager: function (sub) {
        var self = this;
        var manifestDirPath = cc.sys.writablePath + sub + '/';
        var manifestFileName = 'sub-' + sub + '.manifest';
        this._removeAssetsManager();
        this._assetsManager = new jsb.AssetsManager(sub + '/' + manifestFileName, manifestDirPath);
        this._assetsManager.retain();
        this._assetsManager.update();
        showDownLoading('正在检查更新中..', '');
        this._assetsManagerListener = new jsb.EventListenerAssetsManager(this._assetsManager, function (event) {
            // console.log('event.getEventCode() = ' + event.getEventCode());
            switch (event.getEventCode()) {
                case jsb.EventAssetsManager.NEW_VERSION_FOUND:
                    // console.log('即将更新..');
                    showDownLoading('即将更新..', '');
                    break;
                case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
                    self._updateFail(sub, '本地manifest错误');
                    break;
                case jsb.EventAssetsManager.UPDATE_PROGRESSION:
                    self._changePercent(event.getPercent().toFixed(2));
                    // console.log(event.getPercent() + '% ..');
                    break;
                case jsb.EventAssetsManager.ASSET_UPDATED:
                    // console.log('资源更新完毕');
                    hideDownLoading();
                    break;
                case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
                case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:
                    self._updateFail(sub, '下载manifest失败  请您尽量在wifi或网络良好的环境下更新~');
                    break;
                case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:
                case jsb.EventAssetsManager.UPDATE_FINISHED:
                    self._newVersion = self._assetsManager.getLocalManifest().getVersion();
                    self._updateSucess(sub);
                    break;
                case jsb.EventAssetsManager.UPDATE_FAILED:
                    self._updateFail(sub, '更新模块文件失败1  请您尽量在wifi或网络良好的环境下更新~');
                    break;
                case jsb.EventAssetsManager.ERROR_UPDATING:
                    self._updateFail(sub, '更新模块文件失败2  请您尽量在wifi或网络良好的环境下更新~');
                    break;
                case jsb.EventAssetsManager.ERROR_DECOMPRESS:
                    self._updateFail(sub, '更新模块文件失败3  请您尽量在wifi或网络良好的环境下更新~');
                    break;
                default:
                    self._updateFail(sub, '更新模块文件失败4  请您尽量在wifi或网络良好的环境下更新~');
                    break;
            }
        });
        cc.eventManager.addListener(this._assetsManagerListener, 1);
    },
    /**
     *加载模块
     * @param sub
     * @param callback
     * @private
     */
    _loadSub: function (sub, callback) {
        if (callback) {
            this._callback = callback;
        }
        this._loadSubJs(sub);
    },
    _loadMain: function (sub, callback) {
        if (callback) {
            this._callback = callback;
        }
        this._loadMainJs(sub);
    },
    /**
     *加载模块代码
     * @param sub
     * @private
     */
    _loadMainJs: function (sub) {
        var submoduleSrc = 'modules/main/' + sub + '/Config.js';
        DeviceUtil.addSearchPath(cc.sys.writablePath + sub + '/');
        var self = this;
        cc.sys.cleanScript(submoduleSrc);
        cc.sys.cleanScript(submoduleSrc + 'c');
        cc.loader.loadJs(submoduleSrc, function () {
            self._loadSunCommonRes(sub);
        });
    },
    /**
     *加载模块代码
     * @param sub
     * @private
     */
    _loadSubJs: function (sub) {
        var submoduleSrc = 'modules/sub/' + sub + '/Config.js';
        DeviceUtil.addSearchPath(cc.sys.writablePath + sub + '/');
        var self = this;
        cc.sys.cleanScript(submoduleSrc);
        cc.sys.cleanScript(submoduleSrc + 'c');
        cc.loader.loadJs(submoduleSrc, function () {
            self._loadSunCommonRes(sub);
        });
    },
    /**
     *加载模块公用资源
     * @param sub
     * @private
     */
    _loadSunCommonRes: function (sub) {
        var self = this;
        var subRes = window[sub]['res'];
        cc.loader.load(_.values(subRes), function () {
            // 把模块的res塞进res里面，会覆盖res里面现有的
            _.assign(res, subRes);
            self._loadSubCommonSrc(sub);
        });
    },
    /**
     *加载模块公用代码
     * @param sub
     * @private
     */
    _loadSubCommonSrc: function (sub) {
        var subSrc = window[sub]['src'];
        var self = this;

        _.forIn(self._oldSubSrc, function (jsfile) {
            cc.sys.cleanScript(jsfile);
            cc.sys.cleanScript(jsfile + 'c');
        });
        _.forIn(subSrc, function (jsfile) {
            cc.sys.cleanScript(jsfile);
            cc.sys.cleanScript(jsfile + 'c');
        });

        self._oldSubSrc = subSrc;

        cc.loader.loadJs(subSrc, function () {
            if (self._callback) {
                self._callback();
            }
        });
    },
    /**
     * 更新成功
     */
    _updateSucess: function (sub) {
        var arr = window[sub] ? window[sub]['src'] : null;
        if (arr) {
            for (var i = 0; i < arr.length; i++) {
                cc.sys.cleanScript(arr[i]);
                cc.sys.cleanScript(arr[i] + 'c');
            }
            delete window[sub]['src'];
            window[sub]['src'] = null;
        }
        cc.textureCache.removeAllTextures();
        cc.spriteFrameCache.removeSpriteFrames();
        this._removeAssetsManager();
        this._saveLocalVersion(sub);
        this._loadSub(sub);
        hideDownLoading();
    },
    /**
     * 更新失败
     * @param sub
     * @param error
     */
    _updateFail: function (sub, error) {
        // console.log('error = ' + error);
        showAlert('拉取模块"' + sub + '"失败: ' + error);
        if (jsb.fileUtils.isDirectoryExist(window.writablePath + sub + '_temp')) {
            jsb.fileUtils.removeDirectory(window.writablePath + sub + '_temp');
        }
        hideDownLoading();
        this._removeAssetsManager();
    },
    /**
     * 存储本地版本号
     * @param sub
     */
    _saveLocalVersion: function (sub) {
        /**
         * 兼容线上包
         */
        if ((app.appId == 71 || app.appId == 1) && sub == app.sub_module.MaJiang_hn) {
            this._saveLocalVersion('majiang');
        }
        if (sub == app.sub_module.MATCH_HALL) {
            this._saveLocalVersion('bisaichang');
        }
        var verjson = getLocalVersion();
        verjson[sub] = this._newVersion;
        cc.sys.localStorage.setItem('sub-version', JSON.stringify(verjson));
    },
    /**
     * 改变percent
     * @param percent
     */
    _changePercent: function (percent) {
        showDownLoading('下载中......', '正在更新: ' + percent + '%');
    },
    /**
     * 删除assetsManager
     */
    _removeAssetsManager: function () {
        if (this._assetsManager) {
            this._assetsManager.release();
            this._assetsManager = null;
        }
        if (this._assetsManagerListener) {
            cc.eventManager.removeListener(this._assetsManagerListener);
            this._assetsManagerListener = null;
        }
    },
    /**
     * 过滤消息
     * @param {Object} message
     * @public
     * */
    filterMessage: function (message) {
        if (DeviceUtil.getDebug()) {
            return;
        }
        var code = message.code;
        if (this._filterCode.indexOf(code) >= 0) {
            message.data.map_ver = getLocalVersion();
            message.data.timestamp = _.now();
            this._messages[code] = message.data;
        }
    },

    /**
     * 获取消息结构
     * @param {String | Number} code
     * @public
     * */
    getMessageData: function (code) {
        if (this._messages.hasOwnProperty(code)) {
            return this._messages[code];
        }
        return {};
    },

    /**
     * 重置登录数据
     * @param{String | Number} code
     * @public
     * */
    resetMessage: function (code) {
        if (this._messages.hasOwnProperty(code)) {
            delete this._messages[code];
        }
    },
    /**
     * 模块更新
     * @public
     */
    subUpdate: function (data) {
        var sub = data.key;
        var version = data.ver;
        var source = data.source;
        var roomid = data.room_id;
        /**
         * 兼容老的版本名称
         */
        if (sub == 'bisaichang') {
            sub = app.sub_module.MATCH_HALL;
        }
        if ((app.appId == 71 || app.appId == 1) && sub == 'majiang') {
            sub = app.sub_module.MaJiang_hn;
        }
        // var club_id = data.club_id;
        var url = data.url;
        if (!sub && data.update == false && source === 'request') {
            SubUpdateUtil.updateSubCallback();
            return;
        }
        if (sub === 'home') {
            showAlert("您的游戏版本过低, 即将执行自动更新", function () {
                clearApp();
                cc.LoaderScene.preload(g_resources, function () {
                    cc.director.runScene(new UpdateScene());
                }, this);
            });
            return;
        }
        showDownLoading('有新的' + sub + '版本:' + version + ',请更新');
        SubUpdateUtil.checkUpdate(url, sub, version, function () {
            if (source === 'login') {
                network.send(2001, SubUpdateUtil.getMessageData(2001));
            } else if (source === 'create') {
                var last3001Data = SubUpdateUtil.getMessageData(3001);
                var timestamp = last3001Data['timestamp'];
                if (getCurTimestampMills() - timestamp <= 30000) {
                    network.send(3001, last3001Data);
                }
            } else if (source === 'join') {
                network.send(3002, {room_id: '' + roomid});
            } else if (source === 'request') {
                hideDownLoading();
                SubUpdateUtil.updateSubCallback();
            } else {
                hideDownLoading();
                showAlert('有新的' + sub + '版本:' + version + ',请更新后进入');
            }
        });
    },
};
